Repository navigation
host: a Clear that cannot remove the rotated log leaves the leaf untouched and silent - #2361
Conversation
Clear removed logs/diagnostics.jsonl.1 inside the write chain but outside a try of its own, so a copy the host could not remove - a directory under that name (EISDIR), a folder without its write bit (EACCES) - rejected the chain before the truncate ran, and the trailing empty catch kept it quiet: the window answered "Cleared the error log." while the leaf still held every line. The removal keeps a try of its own now, names the leftover on one stderr line that carries no folder, and the truncate runs whether or not it succeeded. Fixes ThinkFlowLab#2358.
|
@Birfy review please — tip Tier T3 ( Checks at the tip: 14 success + 1 failure, the only red being What it does: |
|
Verdict: PASS at e3b27c0 Ran at this tip: Red first: with only Checks at this tip, read from Scope, read on the tarball: 6 files, +182/−9. The only product change is Tier: T3, on the content rule Not run here: Attestation note: this verdict is at the head the PR names, the PR is not draft, |
Fixes #2358
Owner: Dev-2
Reviewer: Birfy
Claim-Id: 7d328f20e3084f528c4b2b09cdd1d4c9
Branch: dev/2-p523-clear-rm-guard
Base: 8c58f3a
Tip: e3b27c0
Tree: 30425d27e18c2ce81f5e81edf56e2643edbed913
Diff: 6 files, +182/−9
Tier: T3
why: ["core/test/diagnostics.test.js: /\.(only|skip)\(/"]
basis: core/src/host/diagnostics.js=T2, core/test/diagnostics.test.js=T1, changelog.d/2358-diagnostics-clear-rm.fixed.md=T1, patches/ds-bot/0001-core-fixes.patch=T1, patches/ds-bot/0007-version-and-tooling.patch=T1, docs/subsystems/core-host.md=T0
Docs-changed: docs/subsystems/core-host.md:409 — the Clear sentence now says the removal keeps a
tryof its own and the truncate runs whether or not it succeeded, so the page's "cleared" matches the leaf again.What changed
clear()removed the rotated copy and truncated the leaf in one write chain whose only handler was an empty.catch(() => {}). Thermhad notryof its own, so a copy the host could not remove — a directory under that name (EISDIR), a folder without its write bit (EACCES), a busy file — rejected the chain on that line and thewriteFileone line below never ran.clear()had already setcleared/freshbefore the chain, so the window showed "No errors recorded." and "Cleared the error log." while the leaf still held every line, and nothing reached stderr: the leaf guard above had already passed, sorefuseLeaf()did not fire.rmnow has atryof its own. A failure writes oneconsole.errorline that names the error code and never the folder ([ds-bot] diagnostics log rotated copy not removed: EACCES), and the truncate runs as before, whether or not the removal succeeded. The leftover bytes stay; the log the user asked to clear is empty.fileKindguard keeps its place, its logic and its order: a leaf that is a link is still refused whole and nothing is truncated.clear()keeps its signature and return value;0008andcore/client.jsare untouched.After:
.1that cannot be removed is still there, is now named on stderr, and the leaf is empty — a Clear that says it cleared no longer leaves every line on disk. The normal path is unchanged:rmsucceeds, one truncation,.1gone, no stderr line.Test first
Two deterministic shapes added to
core/test/diagnostics.test.js, both with a writable leaf so the only failure is the removal:#2358: clear truncates the leaf even when the rotated copy cannot be removed—logs/diagnostics.jsonl.1is a directory, sormwithoutrecursiveraisesERR_FS_EISDIR.#2358: clear truncates the leaf when the folder refuses the removal—logs/is0555and the leaf is0644, so the removal raisesEACCES; skipped under root witht.skip, where0555denies nothing, andEISDIRneeds no such guard.Both assert the leaf reads back
'',.1is still present (the directory; the file with its bytes unchanged),entries()is empty, and stderr carries exactly one line that does not contain the home folder.On the clean base with only these tests in the tree:
node --test core/test/diagnostics.test.js→ 30 tests / 28 pass / 2 fail / 0 cancelled; both fail onassert.strictEqual(readFileSync(logPath, 'utf8'), '')—the leaf is truncated although the rotated copy staysandthe leaf is truncated although the folder refused the removal, actual'OLD LINE\n'×4and the 4-line warning record. The untruncated leaf in shape B also proves theEACCESarms before the truncate, as expected. With the fix: 30 / 30 / 0.The "no
.1at all" path stays green throughout —rm(force: true)swallowsENOENT, and the existingclear removes the rotated log, not only the leafcovers it.Generated
patches/ds-bot/0001-core-fixes.patchand0007-version-and-tooling.patchare the mechanicalnode scripts/ds-bot-patches.mjs generateoutput for the two edited files (src/host/diagnostics.js,test/diagnostics.test.js). The product change iscore/src/host/diagnostics.jsplus the test; nothing else in those patches.generateis a no-op on this tree,checkreports 10 patches applying cleanly withcore/equal tods-bot/+ patches,canonicalreports generate is a no-op, andbuild-client.mjs --checkexits 0.0008andcore/client.jswere never ingit statuson this branch.The tier is T3 on the content rule
\.(only|skip)\(matching the root guard'st.skip(line, not on the product change (diagnostics.jsis T2 on its own); thet.skipstays as Node's per-test option form would only be a way around the pattern, not a fix, and CI's runner is not root.Ran
verifyat the committed tip: core lint 74 warnings / 0 errors, plugin lint 36 / 9 / 2 / 16 warnings and 0 errors, scripts lint 1 / 0,arch-docs: OK (6 changed file(s)), and suites 2767 + 570 + 132 + 140 + 411 + 671 + 37 + 26 = 4754 pass / 0 fail / 0 cancelled.Not run: the smoke test and the CI
packagejob's pack check, typecheck and actionlint, whichnpm run verifydoes not run.Checkpoint
{ "pr": 2361, "claim": "Dev-2", "issue": 2358, "summary": "clear() removed the rotated copy inside the write chain but outside a try of its own, so a copy the host could not remove rejected the chain before the truncate ran, and the empty catch kept it quiet: the window said the log was cleared while the leaf held every line. The removal now keeps a try, names the leftover on one stderr line that carries no folder, and the truncate runs whether or not it succeeded. The fileKind guard, clear()'s signature and the removal rule are unchanged.", "files": [ "core/src/host/diagnostics.js", "core/test/diagnostics.test.js", "changelog.d/2358-diagnostics-clear-rm.fixed.md", "docs/subsystems/core-host.md", "patches/ds-bot/0001-core-fixes.patch", "patches/ds-bot/0007-version-and-tooling.patch" ], "checks": { "ran": "TZ=UTC ARCH_DOCS_BASE=8c58f3a1c7a6511abcd2816aa545dded7ab4b99d npm run verify", "result": "green", "at": "e3b27c0075afe3d96ebf8e6a55f797ab05a2a5ac" }, "next": "none \u2014 ready for review" }